package com.unicom.aop.annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;


/**
 * @author liry
 * @version 1.0
 * @date Created on 2021/12/14 15:31
 * Description: 配置切面
 * 切面可使用的注解: Before.class, Around.class, After.class, AfterReturning.class,
 * AfterThrowing.class, Pointcut.class
 */
@Component
// 定义一个切面
@Aspect
// 开启注解版aop功能
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@Import(TestBean.class)
public class AspectJAnnotation {

    public static final Logger log = LoggerFactory.getLogger(AspectJAnnotation.class);

    /**
     * 定义一个切点:
     */
//	@Pointcut("execution(public * com.unicom.aop.test.TestBean.*(..))")
    @Pointcut("execution(public * com.unicom.aop.annotation..*(..))")
    public void testExecution() {
    }


    /**
     * @param joinPoint: 连接点参数
     */
    @Before("testExecution()")
    public void beforeExecutionTest(JoinPoint joinPoint) {
        log.info("-----before test-----");

        // 获得类名，方法名，参数和参数名称。
        Signature signature = joinPoint.getSignature();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

        String[] argumentNames = methodSignature.getParameterNames();

        StringBuilder sb = new StringBuilder(className + "." + methodName + "(");

        for (int i = 0; i < arguments.length; i++) {
            Object argument = arguments[i];
            sb.append(argumentNames[i] + "->");
            sb.append(argument != null ? argument.toString() : "null ");
        }
        sb.append(")");

        log.info("-----前置增强处理: {}, -----", sb.toString());
    }


    @After("testExecution()")
    public void afterExecutionTest(JoinPoint joinPoint) {
        log.info("-----after test-----");
    }


    @Around("testExecution()")
    public Object aroundExecutionTest(ProceedingJoinPoint p) {
        log.info("-----around before 1-----");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        log.info("-----around after 1-----");
        return o;
    }
}
